import React, { Component } from "react";
import ReactDOM from "react-dom";
import {
    FLOW_CONTROL_1,
    FLOW_CONTROL_2,
    FLOW_CONTROL_3,
    FLOW_CONTROL_4
} from "./AppConst";

/**
 * State 组件(状态)
 * React 把组件看成是一个状态机（State Machines）。通过与用户的交互，实现不同状态，然后渲染 UI，
 *  让用户界面和数据保持一致。
   React 里，只需更新组件的 state，然后根据新的 state 重新渲染用户界面（不要操作 DOM）。
   @date: 2020-11-22
 */


class MyClock extends React.Component {
    constructor(props) {
        super(props)
        // 构建一个state:保存的是一个日期对象
        this.state = { date: new Date() }
    }

    render() {
        return (
            <div>
                <h1>Hello,world!</h1>
                <h2>这是第一个测试状态的组件</h2>
                {/* 这里通过使用this.state来修改当前时间 */}
                <h2>现在是{this.state.date.toLocaleTimeString()}.</h2>
            </div>
        );
    }
}

function SampleMyClock() {
    return <MyClock />
}

/** ----------------------  代码的执行流程可以参考： https://www.runoob.com/react/react-state.html ---------------------- */

/**
 * 电子表
 */
class ElectricClock extends React.Component {
    constructor(props) {
        super(props);
        console.log("ElectricClock init...");
        this.state = { date: new Date() }
    }

    tick() {
        console.log("tick run...");
        this.setState(
            { date: new Date() }
        );
    }


    /**
     * 生命周期函数: 被挂载的时候执行
     *  每当 Clock 组件第一次加载到 DOM 中的时候，我们都想生成定时器，这在 React 中被称为挂载
     */
    componentDidMount() {
        console.log("componentDidMount run ...");
        // 开启定时器，并且赋值给timerId,以便清除
        this.timerID = setInterval(
            () => this.tick(),
            1000
        );
    }

    /**
     * 生命周期函数：被反挂载的时候执行
     *  每当 Clock 生成的这个 DOM 被移除的时候，我们也会想要清除定时器，这在 React 中被称为卸载。
     */
    componentWillUnmount() {
        console.log("componentWillUnmount run ...");
        // 清除定时器
        clearInterval(this.timerID)
    }

    render() {
        console.log("render run ...");
        return (
            <div>
                <h1>欢迎使用卡西欧电子表!!!</h1>
                <h2>现在是{this.state.date.toLocaleTimeString()}.</h2>
            </div>
        )
    }
}

function SampleElectricClock() {
    return <ElectricClock />
}

/** ----------------------  代码的执行流程可以参考： https://www.runoob.com/react/react-state.html ---------------------- */


/** ----------------------  数据自顶向下流动 ---------------------- */
/**
 * 父组件或子组件都不能知道某个组件是有状态还是无状态，并且它们不应该关心某组件是被定义为一个函数还是一个类。
    这就是为什么状态通常被称为局部或封装。 除了拥有并设置它的组件外，其它组件不可访问。
 */




/**
 * 日期格式化组件
 * 在日期格式化组件的属性中接收date值
 */
function FormattedDate(props) {
    return <h2>现在是{props.date.toLocaleTimeString()}.</h2>
}

/**
 * 电子表
 */
class BabyElectricClock extends React.Component {
    constructor(props) {
        super(props);
        console.log("ElectricClock init...");
        this.state = { date: new Date() }
    }

    tick() {
        console.log("tick run...");
        this.setState(
            { date: new Date() }
        );
    }


    /**
     * 生命周期函数: 被挂载的时候执行
     *  每当 Clock 组件第一次加载到 DOM 中的时候，我们都想生成定时器，这在 React 中被称为挂载
     */
    componentDidMount() {
        console.log("componentDidMount run ...");
        // 开启定时器，并且赋值给timerId,以便清除
        this.timerID = setInterval(
            () => this.tick(),
            1000
        );
    }

    /**
     * 生命周期函数：被反挂载的时候执行
     *  每当 Clock 生成的这个 DOM 被移除的时候，我们也会想要清除定时器，这在 React 中被称为卸载。
     */
    componentWillUnmount() {
        console.log("componentWillUnmount run ...");
        // 清除定时器
        clearInterval(this.timerID)
    }

    render() {
        console.log("render run ...");
        return (
            <div>
                <h1>欢迎使用宝宝闹钟!!!</h1>
                {/* 在这里传递数据级FormattedDate组件 */}
                <FormattedDate date={this.state.date} />
            </div>
        )
    }
}

function SampleBabyElectricClock() {
    return <BabyElectricClock />
}

/**
 * 这通常被称为自顶向下或单向数据流。 任何状态始终由某些特定组件所有，并且从该状态导出的任何数据或 UI 只能影响树中下方的组件。

   如果你想象一个组件树作为属性的瀑布，每个组件的状态就像一个额外的水源，它连接在一个任意点，但也流下来。 
 *
 */
function SampleElectricClockList() {
    return (
        <div>
            <BabyElectricClock />
            <BabyElectricClock />
            <BabyElectricClock />
        </div>
    );
}
/** ----------------------  数据自顶向下流动 ---------------------- */

function buildComponentUi(flag) {
    console.log("buildComponentUi flag = " + flag);
    switch (flag) {
        case FLOW_CONTROL_1:
            return SampleMyClock();
        case FLOW_CONTROL_2:
            return SampleElectricClock();
        case FLOW_CONTROL_3:
            return SampleBabyElectricClock();
        case FLOW_CONTROL_4:
            return SampleElectricClockList();
    }
}



/**
 * 执行渲染
 * @param {标记位} flag 
 */
function execRender(flag) {
    console.log("execRender flag = " + flag);
    ReactDOM.render(
        buildComponentUi(flag),
        document.getElementById('container')
    );
}


function stateMain() {
    execRender(FLOW_CONTROL_4);
}


export { stateMain }

/**
 * 箭头函数 Lambda 表达式参考资料
 *  https://www.runoob.com/react/react-state.html
 */